/*
 * @Author: 0x9DEFA478
 * @Date: 2025-07-26 19:36:04
 * @LastEditTime: 2025-09-15 21:58:05
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "HMakeDependencyChain.hpp"
#include <atomic>
#include <thread>
#include <list>
#include "Container/H_Stack.hpp"


namespace HMake{

  DependencyChain::Item::Item()noexcept:targetValid(false),targetLastUpdateTime(0),isIntoCount(true),status(StatusEnum::Init),ioexclusive(false){}

  DependencyChain::Item::~Item()noexcept{}

  void DependencyChain::Item::UpdateTargetStatus(){
    auto targetStatus=TargetStatus();
    targetValid=targetStatus.first;
    targetLastUpdateTime=targetStatus.second;
  }

  void DependencyChain::Item::ForceSetNewExist(){
    targetValid=true;
    targetLastUpdateTime=UINT64_MAX;
  }

  H::size DependencyChain::Item::GetDependencyCount()const{
    H::Tree::RedBlack<Pointer::TypePointer,int> itemArray;

    struct StackItem{
      ChainMap::ConstIterator iterator;
      ChainMap::ConstIterator end;

      explicit StackItem(const ChainMap& map):iterator(map.begin()),end(map.end()){}
    };
    
    H::Stack<StackItem> stack;

    StackItem currentStatus(dependencyMap);

    for(;;){
      
      if(currentStatus.iterator!=currentStatus.end){
        auto Item=*currentStatus.iterator;
        currentStatus.iterator++;
        if(Item.Key()->isIntoCount){
          itemArray.Insert(Item.Key(),0);
        }

        stack.Push(currentStatus);
        currentStatus=StackItem(Item.Key()->dependencyMap);
        continue;
      }

      if(stack.Empty()){
        break;
      }
      currentStatus=stack.Top();
      stack.Pop();
    }

    return itemArray.Count();
  }


  int DependencyChain::Run(Item::Pointer root,int MaxJob){
    H::Lock lock;
    H::Event doneEvent;
    auto threadDoneEvent=H::PointerShare<H::Event>::Array(MaxJob);
    std::list<std::thread> threadList;

    H::Lock exclusiveLock;
    auto threadExclusiveLock=H::PointerShare<H::Lock>::Array(MaxJob);
    
    std::atomic_bool ExitSignal=false;
    std::atomic_int ExitErrorCode=0;
    
    if(MaxJob<1){
      MaxJob=1;
    }

    auto run=[&lock,&doneEvent,threadDoneEvent,&exclusiveLock,threadExclusiveLock,&ExitSignal,&ExitErrorCode,root,MaxJob](int JobIndex){
      
      for(;;){
        Item* task;
        int res;
        bool ioexclusive;

        if(ExitSignal.load(std::memory_order::consume)||(ExitErrorCode.load(std::memory_order::consume)!=0)){
          break;
        }

        lock.Lock();
        task=FindTask(root);
        if(task!=nullptr){
          SetRun(task);
        }
        lock.Unlock();

        if(task==nullptr){
          doneEvent.Trigger();//没有新任务了所有的任务才有可能完成
          threadDoneEvent[JobIndex].Acquire();//等待所有任务结束或者有任务更新
          continue;
        }

        ioexclusive=task->IOExclusive();

        if(ioexclusive){//独占IO锁
          exclusiveLock.Lock();
          for(int i=0;i<MaxJob;i++){
            if(i!=JobIndex){
              threadExclusiveLock[i].Lock();
            }
          }
        }else{
          threadExclusiveLock[JobIndex].Lock();
        }
        res=RunItem(task,lock);
        if(res!=0){
          ExitErrorCode.store(res);
        }
        if(ioexclusive){//独占IO锁
          for(int i=0;i<MaxJob;i++){
            if(i!=JobIndex){
              threadExclusiveLock[i].Unlock();
            }
          }
          exclusiveLock.Unlock(); 
        }else{
          threadExclusiveLock[JobIndex].Unlock();
        }

        for(int i=0;i<MaxJob;i++){
          if(i!=JobIndex){
            threadDoneEvent[i].Trigger();
          }
        }

        if(res!=0){
          doneEvent.Trigger();
          break;
        }
      }
    };

    for(int i=0;i<MaxJob;i++){
      threadList.emplace_back(run,i);
    }

    for(;;){
      bool IsDone;
      int ExitCode;

      lock.Lock();
      IsDone=root->status==Item::StatusEnum::Done;
      ExitCode=ExitErrorCode.load(std::memory_order::consume);
      lock.Unlock();

      if(IsDone||(ExitCode!=0)){
        break;
      }
      
      doneEvent.Acquire();
    }

    ExitSignal.store(true,std::memory_order::release);
    for(int i=0;i<MaxJob;i++){
      threadDoneEvent[i].Trigger();
    }
    for(auto& Item:threadList){
      Item.join();
    }

    return ExitErrorCode.load(std::memory_order::consume);
  }

  bool DependencyChain::AddDependency(Item::Pointer& item,Item::Pointer& depItem){
    if(item==nullptr){
      return false;
    }
    if(depItem==nullptr){
      return true;
    }
    if(item->status!=Item::StatusEnum::Init){
      return false;
    }
    if(depItem->status!=Item::StatusEnum::Init){
      return false;
    }

    if(item->dependencyMap.end()!=item->dependencyMap.Find(depItem)){
      throw std::logic_error("DependencyChain::AddDependency(): 依赖链结构发生了错误 可能是重复添加");
    }

    if(depItem->supportMap.end()!=depItem->supportMap.Find(item)){
      throw std::logic_error("DependencyChain::AddDependency(): 依赖链结构发生了错误");
    }

    depItem->supportMap.Insert(item,0);
    item->dependencyMap.Insert(depItem,0);

    //一旦成为别的Item的依赖, 都将其itemCollection转移到被依赖链的头部, 这保证智能指针都集中在依赖链头部, 避免原来用智能指针构造的树会引起析构深度大的问题
    Item* header=item;
    while(!header->supportMap.Empty()){
      header=header->supportMap.begin()->Key();
      if(header==nullptr){
        throw std::logic_error("DependencyChain::AddDependency(): 依赖链结构出现了null节点");
      }
    }
    if(!depItem->itemCollection.Empty()){
      for(auto& Item:depItem->itemCollection){
        header->itemCollection.Insert(Item);
      }
      depItem->itemCollection.Clear();
    }
    header->itemCollection.Insert(depItem,0);

    return true;
  }


  DependencyChain::Item* DependencyChain::FindTask(Item* root){
    struct StackItem{
      using ChainMap=DependencyChain::Item::ChainMap;

      ChainMap::Iterator iterator;
      ChainMap::Iterator end;

      explicit StackItem(ChainMap& map):iterator(map.begin()),end(map.end()){}
    };

    H::Stack<StackItem> stack;
    StackItem::ChainMap rootList={{root,0}};

    StackItem currentStatus(rootList);

    for(;;){
      while(currentStatus.iterator!=currentStatus.end){
        auto& itemPointer=currentStatus.iterator->Key();
        currentStatus.iterator++;
        if(!itemPointer->dependencyMap.Empty()){
          stack.Push(currentStatus);
          currentStatus=StackItem(itemPointer->dependencyMap);
          continue;
        }

        if(itemPointer->status!=Item::StatusEnum::Init){
          continue;
        }

        if(!itemPointer->targetValid){
          return itemPointer;
        }

        for(auto& Item:itemPointer->dependencyMap_Done){
          if(Item.Key()->targetLastUpdateTime>itemPointer->targetLastUpdateTime){
            return itemPointer;
          }
        }

        SetDone(itemPointer,false);//依赖链已经被修改, 迭代器可能失效
        stack=H::Stack<StackItem>();
        currentStatus=StackItem(rootList);
      }

      if(stack.Empty()){
        break;
      }
      currentStatus=stack.Top();
      stack.Pop();
    }

    return nullptr;
  }

  void DependencyChain::SetRun(Item* item){
    item->status=Item::StatusEnum::Running;
  }

  int DependencyChain::RunItem(Item* item,H::Lock& lock){
    int r;
    r=item->Run();
    if(r!=0){
      return r;
    }
    lock.Lock();
    SetDone(item,true);
    lock.Unlock();
    return r;
  }

  void DependencyChain::SetDone(Item* item,bool IsUpdate){
    if(IsUpdate){
      item->UpdateTargetStatus();
    }
    item->status=Item::StatusEnum::Done;
    for(auto& Item:item->supportMap){
      auto& ItemPointer=Item.Key();
      ItemPointer->dependencyMap.Erase(item);
      ItemPointer->dependencyMap_Done.Insert(item,0);
    }
    item->DoneEvent(IsUpdate);
  }

}

